﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using TireService.Data;
using DevExpress.Web.ASPxEditors;
using DevExpress.Web.ASPxCallback;

namespace TireService.Website.Booking
{
    public partial class GruppeBooking : System.Web.UI.Page
    {

        public int GroupServiceCarScheduleId
        {
            get
            {
                if (Session["groupbooking_groupservicecarscheduleid"] != null)
                    return (int)Session["groupbooking_groupservicecarscheduleid"];
                else
                    return 0;
            }
            set
            {
                Session["groupbooking_groupservicecarscheduleid"] = value;
            }
        }

        public int CustomerId
        {
            get
            {
                if (Session["groupbooking_customerid"] != null)
                    return (int)Session["groupbooking_customerid"];
                else
                    return 0;
            }
            set
            {
                Session["groupbooking_customerid"] = value;
            }
        }

        public int CarId
        {
            get
            {
                if (Session["groupbooking_carid"] != null)
                    return (int)Session["groupbooking_carid"];
                else
                    return 0;
            }
            set
            {
                Session["groupbooking_carid"] = value;
            }
        }

        public int ContainerId
        {
            get
            {
                if (Session["groupbooking_containerid"] != null)
                    return (int)Session["groupbooking_containerid"];
                else
                    return 0;
            }
            set
            {
                Session["groupbooking_containerid"] = value;
            }
        }

        public int TaskId
        {
            get
            {
                if (Session["groupbooking_taskid"] != null)
                    return (int)Session["groupbooking_taskid"];
                else
                    return 0;
            }
            set
            {
                Session["groupbooking_taskid"] = value;
            }
        }

        public int ServiceCarScheduleDetailId
        {
            get
            {
                if (Session["groupbooking_servicecarscheduledetailid"] != null)
                    return (int)Session["groupbooking_servicecarscheduledetailid"];
                else
                    return 0;
            }
            set
            {
                Session["groupbooking_servicecarscheduledetailid"] = value;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (Page.IsPostBack != true)
            {
                // Reset hidden session values
                Session["groupbooking_groupservicecarscheduleid"] = null;
                Session["groupbooking_containerid"] = null;
                Session["groupbooking_customerid"] = null;
                Session["groupbooking_carid"] = null;
                Session["groupbooking_taskid"] = null;
                Session["groupbooking_servicecarscheduledetailid"] = null;


                // Get id for GroupServiceCarSchedule
                string id = Request.QueryString["id"];

                //// For testing purposes
                //string id = "5e8c0489-ceb3-4716-ada6-4cf22f17902b";

                if (id != string.Empty)
                {
                    TireServiceDB db = new TireServiceDB();

                    // Fetch GroupServiceCarSchedule
                    GroupServiceCarSchedule group = db.GetGroupServiceCarSchedule(new Guid(id));

                    if (group != null)
                    {
                        if (group.InActive)
                        {

                        }
                        else
                        {
                            // Load start picture for booking
                            lblAddress.Text = group.Address + ", " + group.ZipCode + " " + group.City;
                            lblInfoOnCarParking.Text = group.InfoOnCarParking;

                            // Store id and container in hidden property field
                            this.GroupServiceCarScheduleId = group.GroupServiceCarScheduleId;
                            this.ContainerId = group.ContainerId;
                        }
                    }
                    else
                    {
                        // Redirect user back to start page
                        Response.Redirect("~/Index.aspx");
                    }
                }
                else
                {
                    // Redirect user back to start page
                    Response.Redirect("~/Index.aspx");
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        protected void callbackUserInformationPanel_Callback(object source, DevExpress.Web.ASPxClasses.CallbackEventArgsBase e)
        {
            try
            {
                // Get registration number from client
                string RegistrationNumber = e.Parameter;

                // Initiate data layer
                TireServiceDB db = new TireServiceDB();

                // Get car
                List<Car> cars = db.GetCarsByRegistrationNumber(RegistrationNumber).Where(p => p.CarStatusId != (int)Shared.CarStatus.InActive).ToList();

                // Preset result for client
                hfExistingBooking["ExistingBooking"] = false;

                // Validate car
                if (cars.Count == 0)
                {
                    throw new ArgumentException("Det angivne registreringsnummer kunne ikke findes - venligst kontakt vores kundesupport.");
                }
                if (cars.Count > 1)
                {
                    throw new ArgumentException("Det angivne registreringsnummer findes flere gange i vores system - venligst kontakt vores kundesupport for at booke din tid.");
                }

                // Get car and customer
                Car car = cars.First();
                Customer customer = db.GetCustomer(car.CustomerId);

                // Validate if entered registration number is related to customer
                bool CustomerBelongsToGroup = false;

                // Fetch GroupServiceCarSchedule
                GroupServiceCarSchedule group = db.GetGroupServiceCarSchedule(this.GroupServiceCarScheduleId);
                int group_customerid = group.CustomerId;

                if (customer.CustomerId == group_customerid)
                {
                    CustomerBelongsToGroup = true;
                }
                else
                {
                    if (customer.ParentCustomerId != null)
                    {
                        if (Convert.ToInt32(customer.ParentCustomerId) == group_customerid)
                        {
                            CustomerBelongsToGroup = true;
                        }
                        else
                        {
                            // DrillUp from customer to parentcustomer until top or group_customerid is reached
                            CustomerBLL customerBLL = new CustomerBLL();
                            if (customerBLL.FindCustomerIdInHieraki(db, group_customerid, Convert.ToInt32(customer.ParentCustomerId)))
                            {
                                CustomerBelongsToGroup = true;
                            }
                            else
                            {
                                CustomerBelongsToGroup = false;
                            }
                        }                        
                    }
                    else
                    {
                        CustomerBelongsToGroup = false;
                    }
                }

                if (!CustomerBelongsToGroup)
                {
                    // No parent customer exist - raise error
                    throw new ArgumentException("Det angivne registreringsnummer høre ikke til denne booking gruppe - venligst kontakt vores kundesupport.");
                }

                // Show customer and car info
                lblName.Text = customer.Name;
                lblPhone1.Text = customer.Phone1;
                lblPhone2.Text = customer.Phone2 ?? "-";
                lblEmail.Text = customer.Email;

                lblCarBrand.Text = db.GetCarBrandDescription(car.CarBrandId);
                lblModel.Text = car.Model;
                lblRegistrationNumber.Text = car.RegistrationNumber;
                lblYear.Text = car.Year.ToString();

                // Validate status of car - is it ready for tirechange?
                if (car.CarStatusId == (int)Shared.CarStatus.PlannedTireChange)
                {
                    // Car har already a planned tireset - change date
                    int[] tasktypestatus = new int[] { (int)Shared.TaskTypeStatus.ServiceDrive_Planned, (int)Shared.TaskTypeStatus.ServiceDrive_Replan };

                    List<Task> tasks = db.GetTasksByCarAndTaskTypeStatus(car.CarId, tasktypestatus);
                    
                    int taskid = 0;

                    foreach (Task task in tasks)
                    {
                        // Check if taskdetails contain TireChange
                        if (db.TaskDetails.Where(p => p.TaskDetailTypeId == (int)Shared.TaskDetailType.ServiceDrive_ChangeTire & p.TaskId == task.TaskId).Count() == 1)
	                    {
                            taskid = task.TaskId;
	                    }
                    }

                    if (taskid != 0)
                    {
                        // Task was found
                        ServiceCarScheduleDetail detail = db.GetServiceCarScheduleDetailByTaskId(taskid);

                        if (detail == null)
                        {
                            throw new ArgumentException("Hjulskift allerede planlagt for din bil - kontakt venligst vores kundesupport for at ændre din booking.");
                        }
                        else
                        {
                            // Prepare input to client to tell that booking already exists
                            hfExistingBooking["ExistingBooking"] = true;

                            // Show info on booking to user
                            lblExistingBookingAddress.Text = detail.ToAddress + ", " + detail.ToZipCode + " " + detail.ToCity;
                            lblExistingBookingDate.Text = detail.ScheduleDate.ToShortDateString();
                            lblExistingBookingTimeslot.Text = detail.StartTime.ToString() + " - " + detail.EndTime.ToString();

                            // Store TaskId and ServiceCarScheduleDetailId if that booking is changed by user in hidden property field
                            this.ServiceCarScheduleDetailId = detail.ServiceCarScheduleDetailId;
                            this.TaskId = taskid;
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Hjulskift allerede planlagt for din bil - kontakt venligst vores kundesupport for at ændre din booking.");
                    }
                }
                if (car.CarStatusId == (int)Shared.CarStatus.AwaitsTireChangePlanning)
	            {
		            // Have task created and awaits tirechange - no action needed

                    // Car awaits planning date
                    int[] tasktypestatus = new int[] { (int)Shared.TaskTypeStatus.ServiceDrive_Created, (int)Shared.TaskTypeStatus.ServiceDrive_Replan };

                    List<Task> tasks = db.GetTasksByCarAndTaskTypeStatus(car.CarId, tasktypestatus);

                    int taskid = 0;

                    foreach (Task task in tasks)
                    {
                        // Check if taskdetails contain TireChange
                        if (db.TaskDetails.Where(p => p.TaskDetailTypeId == (int)Shared.TaskDetailType.ServiceDrive_ChangeTire & p.TaskId == task.TaskId).Count() == 1)
                        {
                            taskid = task.TaskId;
                        }
                    }

                    if (taskid != 0)
                    {
                        // Store TaskId for booking creation
                        this.TaskId = taskid;
                    }
                    else
                    {
                        throw new ArgumentException("Hjulskift allerede planlagt for din bil - kontakt venligst vores kundesupport for at ændre din booking.");
                    }

	            }
                if (car.CarStatusId != (int)Shared.CarStatus.AwaitsTireChangePlanning & car.CarStatusId != (int)Shared.CarStatus.PlannedTireChange)
	            {
                    // Car status is not correct for tirechange booking
                    throw new ArgumentException("Din bil står pt. ikke angivet til at skulle have skiftet hjul nu her - kontakt vores kundesupport for at booke din tid.");
	            }

                // Validate if car can be handled (must be on correct container)
                TireSet tireset = db.GetTireSets(car.CarId).SingleOrDefault(p => p.ContainerCargoRoomId != null);
                if (tireset == null)
                {
                    throw new ArgumentException("Vi har desværre ikke hjulene til den angivne bil opbevaret - kontakt vores kundesupport for at booke din tid.");
                }
                else
                {
                    // Validate
                    ContainerCargoRoom cargoroom = db.GetContainerCargoRoom(Convert.ToInt32(tireset.ContainerCargoRoomId));

                    if (cargoroom == null)
                    {
                        throw new ArgumentException("Vi har desværre ikke hjulene til den angivne bil opbevaret - kontakt vores kundesupport for at booke din tid.");
                    }
                    else
                    {
                        if (cargoroom.ContainerId != this.ContainerId)
                        {
                            throw new ArgumentException("Dine hjul er opbevaret på et af vores andre lagre, som gør at vi ikke kan komme på denne adresse og skifte dine hjul - kontakt vores kundesupport for at booke din tid.");
                        }
                    }
                }

                // Store car and customer in property

                // Store car and customer in hidden property field
                this.CarId = car.CarId;
                this.CustomerId = customer.CustomerId;

                // Get scheduledays and capacity
                List<ServiceCarSchedule> schedules = db.GetServiceCarSchedulesByGroupServiceCarScheduleId(this.GroupServiceCarScheduleId).Where(p => p.ScheduleDate > DateTime.Now).ToList();

                if (schedules == null)
                {
                    throw new ArgumentException("Der eksisterer desværre ingen ledige tider i valgt booking område - venligst kontakt vores kundesupport for at booke din tid.");
                }
                else
                {
                    // Clear dates
                    rbtnScheduleDates.Items.Clear();

                    List<ListEditItem> dates = new List<ListEditItem>();
                    ListEditItem date0 = new ListEditItem();

                    date0.Value = 0;
                    date0.Text = "Jeg kan ingen af dato'erne";

                    rbtnScheduleDates.Items.Add(date0);

                    // Bind list to radiobutton list
                    foreach (ServiceCarSchedule schedule in schedules.OrderBy(p => p.ScheduleDate))
                    {
                        // Get free capacity
                        int AvailableCapacity = db.ServiceCarScheduleDetails.Where(p => p.ServiceCarId == schedule.ServiceCarId & p.ScheduleDate == schedule.ScheduleDate & p.ScheduleDetailTypeId == (int)Shared.ScheduleDetailType.Available).Count();

                        if (AvailableCapacity > 0)
                        {
                            ListEditItem dateitm = new ListEditItem();

                            dateitm.Value = schedule.ServiceCarScheduleId;
                            dateitm.Text = schedule.ScheduleDate.ToShortDateString() + " (" + AvailableCapacity.ToString() + " ledige tider)";

                            rbtnScheduleDates.Items.Add(dateitm);    
                        }
                    }

                    rbtnScheduleDates.DataBind();
                }
            }
            catch (Exception ex)
            {
                // Error
                throw new ArgumentException(ex.Message);
            }
        }

        /// <summary>
        /// Callback function that updates UI with possible timeslot on selected booking date
        /// </summary>
        protected void callbackSelectTimePanel_Callback(object source, DevExpress.Web.ASPxClasses.CallbackEventArgsBase e)
        {
            try
            {
                // Get ServiceCarScheduleId from client
                int ServiceCarScheduleId = Convert.ToInt32(e.Parameter);

                // Initiate data layer
                TireServiceDB db = new TireServiceDB();

                // Get ServiceCarSchedule
                ServiceCarSchedule schedule = db.GetServiceCarSchedule(ServiceCarScheduleId);

                // Get ServiceCarScheduleDetails - only available ones
                List<ServiceCarScheduleDetail> scheduledetails = db.GetServiceCarScheduleDetails(schedule.ServiceCarId, schedule.ScheduleDate).Where(p => p.ScheduleDetailTypeId == (int)Shared.ScheduleDetailType.Available).ToList();

                // Clear timeslots
                rbtnTimeslot.Items.Clear();

                foreach (ServiceCarScheduleDetail scheduledetail in scheduledetails)
                {
                    ListEditItem dateitm = new ListEditItem();

                    dateitm.Value = scheduledetail.ServiceCarScheduleDetailId;
                    dateitm.Text = scheduledetail.StartTime.ToString() + " - " + scheduledetail.EndTime.ToString();

                    rbtnTimeslot.Items.Add(dateitm);
                }
            }
            catch (Exception ex)
            {
                // Error
                throw new ArgumentException(ex.Message);
            }
        }

        /// <summary>
        /// Callback function that saves or updates booking
        /// </summary>
        protected void callBackSaveBooking_Callback(object sender, CallbackEventArgs e)
        {
            try
            {
                // Get input parameters from client (0: servicescheduledetailid, 1: customernote)
                string[] param = e.Parameter.Split('|');

                // Get selected booking from client
                int ServiceCarScheduleDetailId = Convert.ToInt32(param[0]);
                string CustomerNote = param[1].ToString();

                TireServiceDB db = new TireServiceDB();

                ServiceCarScheduleDetail existingdetail = new ServiceCarScheduleDetail();

                // Check if booking already exists
                if (this.ServiceCarScheduleDetailId != 0 & this.ServiceCarScheduleDetailId != null)
                {                    
                    // Get existing booking
                    existingdetail = db.GetServiceCarScheduleDetail(this.ServiceCarScheduleDetailId);

                    // Update timeslot - reset to available status
                    ServiceCarScheduleDetailBLL detailBLL = new ServiceCarScheduleDetailBLL();
                    detailBLL.MakeServiceCarScheduleDetailAvailable(db, existingdetail, true);
                }

                // Get schedule for booking
                ServiceCarScheduleDetail detail = db.GetServiceCarScheduleDetail(ServiceCarScheduleDetailId);

                if (detail == null)
                {
                    throw new ArgumentException("Booking tidsrum blev ikke fundet - venligst prøv igen.");
                }

                if (detail.ScheduleDetailTypeId != (int)Shared.ScheduleDetailType.Available)
                {
                    throw new ArgumentException("Valgte tidsrum er desværre blevet booket af en anden - venligst prøv igen.");
                }

                // Get group schedule
                GroupServiceCarSchedule groupschedule = db.GetGroupServiceCarSchedule(this.GroupServiceCarScheduleId);
                if (groupschedule == null)
                {
                    throw new ArgumentException("Gruppe booking blev ikke fundet - venligst prøv igen.");
                }

                // Get car
                Car car = db.GetCar(this.CarId);
                
                // Get customer
                Customer customer = db.GetCustomer(car.CustomerId);

                // Get task
                Task task = db.GetTask(this.TaskId);

                // Make new booking
                // Insert car on timeslot and update scheduledetail
                detail.CarId = car.CarId;
                detail.ToTireSetId = task.TireSetId;
                detail.CustomerConfirmed = true;
                detail.ToAddress = groupschedule.Address;
                detail.ToZipCode = groupschedule.ZipCode;
                detail.ToCity = groupschedule.City;
                detail.ToCountryId = groupschedule.CountryId;
                detail.ToLatitude = groupschedule.Latitude;
                detail.ToLongitude = groupschedule.Longitude;
                detail.CustomerNote = CustomerNote;
                detail.ScheduleDetailTypeId = (int)Shared.ScheduleDetailType.ServiceDrive;
                detail.CustomerConfirmed = true;

                // Fetch all TaskDetails to see if Task contain TireChange
                List<TaskDetail> taskdetails = db.GetTaskDetails(task.TaskId);

                foreach (TaskDetail taskdetail in taskdetails)
                {
                    if (taskdetail.TaskDetailTypeId == (int)Shared.TaskDetailType.ServiceDrive_ChangeTire)
                    {
                        // Update car with new status        
                        car.CarStatusId = (int)Shared.CarStatus.PlannedTireChange;
                    }
                }

                // Relate Task to ServiceCarScheduleDetail
                detail.TaskId = task.TaskId;

                // Update Task status
                task.TaskTypeStatusId = (int)Shared.TaskTypeStatus.ServiceDrive_Planned;

                // Submit changes to database
                db.SubmitChanges();

                // Prepare outlook calendar file
                // TODO: Make code

                // Prepare email
                EmailNotificationServices emailService = new EmailNotificationServices();

                // Prepare servicecomments notes
                string ServiceComments = ""; 
                if (groupschedule.InfoOnCarParking != null)
                {
                    ServiceComments = "<b>Note omkring parkering</b><br>" + groupschedule.InfoOnCarParking + "<br><br>";
                }
                
                // Send confirmation email to customer
                emailService.Customer_ServiceDriveBookingConfirmation_SendCustomerEmail(customer.CustomerId, customer.Email, car.RegistrationNumber, customer.Name, detail.ScheduleDate.ToShortDateString(), string.Format("{0:t}", detail.StartTime) + " - " + string.Format("{0:t}", detail.EndTime), detail.ToAddress, detail.ToZipCode, detail.ToCity, ServiceComments);

                // Dispose database connection
                db.Dispose();
            }
            catch (Exception ex)
            {
                // Error
                throw new ArgumentException(ex.Message);
            }
        }
    }
}